package pacoteAnalisadorLexico;


import java.util.ArrayList;
import java.util.Iterator;
import pacoteAutomato.Automato;
import pacoteAutomato.Erro;
import pacoteAutomato.Palavra;
import pacoteAutomato.Token;
import pacoteScanner.Scanner;

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */


public class AnalisadorLexico
{
    private Automato automato;
    private ArrayList<Erro> listaErros;
    private ArrayList<ArrayList<Token>> matrizOcorrencia;
    private ArrayList[] tabelaSimbolos;
    private final int RESERVADO = 0;
    private final int IDENTIFICADOR = 1;
    private final int NUMERO = 2;
    private final int OPERADOR = 3;
    private final int DELIMITADOR = 4;
    private final int COMENTARIO = 5;
    private final int FRASE = 6;


    public AnalisadorLexico()
    {
        automato = new Automato();
        listaErros = new ArrayList<Erro>();
        matrizOcorrencia = new ArrayList<ArrayList<Token>>();

        tabelaSimbolos = new ArrayList[7];
        for ( int i = 0; i < tabelaSimbolos.length; i++ ) {
            tabelaSimbolos[i] = new ArrayList<Token>();
        }
    }

    public void preencherEstruturas()
    {

        Palavra palavra = null;
        while(true)//enquanto houver linhas
        {

            palavra = automato.proximoToken();//pego o proximo token no automato
            if (palavra instanceof Token)//se for um TOKEN
            {
                Token token = (Token)palavra;//coloco a referencia correta

                if(token.getTipo().equals("Fim")) //se for o token de FIM DE TEXTO
                {
                    break; //paro o laço
                }
                else
                {
                    Token aux;
                    boolean isInsert = true ;// variavel que controla se o token deve ser inserido ou ñ na tabela
                    //pego a linha correspondente ao tipo na tabela de Simbolos
                    ArrayList<Token> listaSimbolos = tabelaSimbolos[getGrupo(token)];
                    Iterator itr = listaSimbolos.listIterator();//pego o iterator para percorrer a linha
                    while(itr.hasNext())
                    {// pesquisa pra ver se o token ja existe
                        aux= (Token)itr.next();
                        if(token.equals(aux))//se já existe
                        {
                            token=aux; //copio a referencia
                            isInsert = false; //desabilito a inserção pq já existe
                        }
                    }
                    if(isInsert) //se não existe ainda na tabela
                        listaSimbolos.add(token); //faço a inserção

                    inserirNaMatriz(token, automato.getLinha());
                 }
            }
            else
            {
               listaErros.add((Erro)palavra);
            }

        }
    }

    private int getGrupo(Token token)
    {
        String tipo = token.getTipo();
        if(tipo.equalsIgnoreCase("IDENT"))
            return IDENTIFICADOR;
        else if(tipo.equalsIgnoreCase("Palavra Reservada"))
            return RESERVADO;
        else if(tipo.equalsIgnoreCase("NUM") || tipo.equalsIgnoreCase("NUMDECIM") || tipo.equalsIgnoreCase("NUM_NUM"))
            return NUMERO;
        else if(tipo.equalsIgnoreCase("COMENTL") || tipo.equalsIgnoreCase("PFIM"))
            return COMENTARIO;
        else if(tipo.equalsIgnoreCase("PONTVIRG") ||
                tipo.equalsIgnoreCase("ABREPARENT") ||
                tipo.equalsIgnoreCase("FECHAPARENT") ||
                tipo.equalsIgnoreCase("ABRECHAVE") ||
                tipo.equalsIgnoreCase("FECHACHAVE") ||
                tipo.equalsIgnoreCase("ABRECOLCH") ||
                tipo.equalsIgnoreCase("VIRGULA") ||
                tipo.equalsIgnoreCase("FECHACOLCH"))
            return DELIMITADOR;
        else if(tipo.equalsIgnoreCase("FIMFRASE"))
            return FRASE;

        else
            return OPERADOR;
    }

    private void inserirNaMatriz(Token token, int linha)
    {
        int index = linha -1;
        if(matrizOcorrencia.size() <= index)
        {
            int dif = index - matrizOcorrencia.size();
            while(dif>=0)
            {
                matrizOcorrencia.add(new ArrayList<Token>());
                dif--;
            }
        }
        matrizOcorrencia.get(index).add(token);
    }

    public ArrayList<Erro> getListaErros()
    {
        return listaErros;
    }

    public ArrayList<ArrayList<Token>> getMatrizOcorrencia()
    {
        return matrizOcorrencia;
    }

    public ArrayList getPalavrasReservadas()
    {
        return tabelaSimbolos[RESERVADO];
    }
    public ArrayList getIdentificadores()
    {
        return tabelaSimbolos[IDENTIFICADOR];
    }
    public ArrayList getNumeros()
    {
        return tabelaSimbolos[NUMERO];
    }
    public ArrayList getOperadores()
    {
        return tabelaSimbolos[OPERADOR];
    }
    public ArrayList getComentarios()
    {
        return tabelaSimbolos[COMENTARIO];
    }
    public ArrayList getDelimitadores()
    {
        return tabelaSimbolos[DELIMITADOR];
    }

    public ArrayList[] getTabelaSimbolos() {
        return tabelaSimbolos;
    }
    public ArrayList getFrases()
    {
        return tabelaSimbolos[FRASE];
    }




//    public static void main(String[] args)
//    {
//        Scanner scanner = Scanner.getScanner();
//     // scanner.setTexto("teste\n\n\nnovo");
//        scanner.setTexto("package pacoteAutomato;/* * To change this template, choose Tools | Templates * and open the template in the editor. */public class Token implements Palavra{    private String tipo;  private String lexema; public Token(String tipo, String lexema)    {        this.tipo = tipo;      this.lexema = lexema; }public boolean equals(Token t) {  boolean ret = false;if (this.lexema.equals(t.getLexema()))     ret = true;");
//        AnalisadorLexico teste = new AnalisadorLexico();
//        teste.preencherEstruturas();
//        System.out.println("TOKENS");
//        ArrayList<ArrayList<Token>> mt = teste.getMatrizOcorrencia();
//        for(int j=0; j<mt.size(); j++)
//            for(int i=0; i< mt.get(j).size(); i++)
//            {
//                System.out.println("linha "+(j+1)+" "+mt.get(j).get(i));
//            }
//        System.out.println("ERROS");
//        ArrayList<Erro> erro = teste.getListaErros();
//        for(int i=0; i< erro.size(); i++)
//            {
//                System.out.println("linha "+(i+1)+" "+erro.get(i));
//            }
//
//
//    }
}
